package com.gel.codegeneration.core;

import cn.hutool.json.JSONUtil;
import com.gel.codegeneration.ai.AiCodeGenerationService;
import com.gel.codegeneration.ai.AiCodeGenerationServiceFactory;
import com.gel.codegeneration.ai.model.entity.HtmlCodeResult;
import com.gel.codegeneration.ai.model.entity.MultiFileResult;
import com.gel.codegeneration.ai.model.enums.CodeGenTypeEnum;
import com.gel.codegeneration.ai.model.message.AiResponseMessage;
import com.gel.codegeneration.ai.model.message.ToolExecutedMessage;
import com.gel.codegeneration.ai.model.message.ToolRequestMessage;
import com.gel.codegeneration.common.enums.ErrorCode;
import com.gel.codegeneration.convention.exception.BusinessException;
import com.gel.codegeneration.core.parser.CodeParserExecutor;
import com.gel.codegeneration.core.saver.CodeSaveExecutor;
import dev.langchain4j.service.TokenStream;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.io.File;

/**
 * @BelongsProject: code-generation-platform
 * @BelongsPackage: com.gel.codegeneration.core
 * @Author: gel
 * @CreateTime: 2025-08-22  11:29
 * @Description: TODO
 * @Version: 1.0
 */
@Slf4j
@Service
public class AiCodeGeneratorFacade {
//    @Resource
//    private AiCodeGenerationService aiCodeGenerationService;
    @Resource
    private AiCodeGenerationServiceFactory aiCodeGenerationServiceFactory;

    /**
     * @description: 统一入口
     * @author: gel
     * @param: [userMessage, codeGenType]
     * @return: java.io.File
     **/
    public  File generateAndSaveCode(String userMessage, CodeGenTypeEnum codeGenType,Long appId) {
        if (codeGenType == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"请选择代码生成类型");
        }
        AiCodeGenerationService aiCodeGenerationService = aiCodeGenerationServiceFactory.getAiCodeGenerationService(appId);
        return switch (codeGenType) {
            case HTML->{
                HtmlCodeResult htmlCodeResult = aiCodeGenerationService.generateHtmlCode(userMessage);
                yield  CodeSaveExecutor.executeSaver(htmlCodeResult, CodeGenTypeEnum.HTML,appId);
            }

            case MULTI_FILE->{
                MultiFileResult multiFileResult = aiCodeGenerationService.generateMultiFileCode(userMessage);
                yield  CodeSaveExecutor.executeSaver(multiFileResult, CodeGenTypeEnum.MULTI_FILE,appId);

            }

            default->{
                String errorMsg = "不支持的代码生成类型：" + codeGenType.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,errorMsg);
            }
        };
    }
//
//    /**
//     * @description: 生成html文件并保存
//     * @author: gel
//     * @param: [userMessage]
//     * @return: java.io.File
//     **/
//
//    public File generateAndSaveHtmlCode(String userMessage){
//        HtmlCodeResult result = aiCodeGenerationService.generateHtmlCode(userMessage);
//        return CodeFileSaver.saveHtmlCodeResult(result);
//    }
//    /**
//     * @description: 生成多文件并保存
//     * @author: gel
//     * @param: [userMessage]
//     * @return: java.io.File
//     **/
//    public File generateAndSaveMultiFileCode(String userMessage){
//        MultiFileResult result = aiCodeGenerationService.generateMultiFileCode(userMessage);
//        return CodeFileSaver.saveMultiFileResult(result);
//    }
    /**
     * @description: 流式统一入口
     * @author: gel
     * @param: [userMessage, codeGenType]
     * @return: java.io.File
     **/
    public  Flux<String> generateAndSaveCodeStream(String userMessage, CodeGenTypeEnum codeGenType,Long appId) {
        if (codeGenType == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"请选择代码生成类型");
        }
        AiCodeGenerationService aiCodeGenerationService = aiCodeGenerationServiceFactory.getAiCodeGenerationService(appId,codeGenType);

        return switch (codeGenType) {
            case HTML->{
                Flux<String> result = aiCodeGenerationService.generateHtmlCodeStream(userMessage);
                yield processCodeStream(result, CodeGenTypeEnum.HTML,appId);
            }

            case MULTI_FILE->{
                Flux<String> result = aiCodeGenerationService.generateMultiFileCodeStream(userMessage);
                yield processCodeStream(result, CodeGenTypeEnum.MULTI_FILE,appId);
            }
            case VUE_PROJECT -> {
                System.out.println(appId);
                System.out.println(userMessage);
                TokenStream tokenStream = aiCodeGenerationService.generateVueProjectCodeStream(appId, userMessage);
                yield processTokenStream(tokenStream);
            }

            default->{
                String errorMsg = "不支持的代码生成类型：" + codeGenType.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,errorMsg);}
        };
    }

    //将tokemStream转换为Flux，将结果封装成指定类
    private Flux<String> processTokenStream(TokenStream tokenStream) {
        return  Flux.create(sink->{
            tokenStream.onPartialResponse(partialResponse->{
                    //ai响应结果
                        AiResponseMessage aiResponseMessage = new AiResponseMessage(partialResponse);
                        sink.next(JSONUtil.toJsonStr(aiResponseMessage));
                    })
                    //工具调用的流式输出
                     .onPartialToolExecutionRequest((index, toolExecutionRequest)->{
                        ToolRequestMessage toolRequestMessage = new ToolRequestMessage(toolExecutionRequest);
                        sink.next(JSONUtil.toJsonStr(toolRequestMessage));
                    })
                    //工具执行完成结果
                    .onToolExecuted(toolExecution->{
                        ToolExecutedMessage toolExecutedMessage = new ToolExecutedMessage(toolExecution);
                        sink.next(JSONUtil.toJsonStr(toolExecutedMessage));
                    })
                    //输出完成
                    .onCompleteResponse(completeResponse->{
                        sink.complete();
                    })
                    .onError( error->{
                        error.printStackTrace();
                        sink.error(error);
                    }).start();
        });
    }

    public  Flux<String> processCodeStream(Flux<String> codeStream, CodeGenTypeEnum codeGenType,Long appId) {
        StringBuffer codeBuilder = new StringBuffer();
        return  codeStream.doOnNext(chunk->{
            codeBuilder.append(chunk);
        }).doOnComplete(()->{
            try{
                String completeHtmlCode = codeBuilder.toString();
                Object obj = CodeParserExecutor.executeParser(completeHtmlCode, codeGenType);
                CodeSaveExecutor.executeSaver(obj, codeGenType,appId);
            }catch (Exception e){
                log.error("代码保存失败,appId:{},error:{}",e.getMessage());
            }

        });
    }
//    /**
//     * @description: 流式生成html文件并保存
//     * @author: gel
//     * @param: [userMessage]
//     * @return: java.io.File
//     **/
//    public Flux<String> generateAndSaveHtmlCodeStream(String userMessage){
//        Flux<String> result = aiCodeGenerationService.generateHtmlCodeStream(userMessage);
//        StringBuffer codeBuilder = new StringBuffer();
//        return  result.doOnNext(chunk->{
//            codeBuilder.append(chunk);
//
//        }).doOnComplete(()->{
//            String completeHtmlCode = codeBuilder.toString();
//            Object htmlCodeResult = CodeParserExecutor.executeParser(completeHtmlCode, CodeGenTypeEnum.HTML);
//            CodeSaveExecutor.executeSaver(htmlCodeResult, CodeGenTypeEnum.HTML);
//        });
//    }
//    /**
//     * @description: 流式生成多文件并保存
//     * @author: gel
//     * @param: [userMessage]
//     * @return: java.io.File
//     **/
//    public Flux<String> generateAndSaveMultiFileCodeStream(String userMessage){
//        Flux<String> result = aiCodeGenerationService.generateMultiFileCodeStream(userMessage);
//        StringBuffer codeBuilder = new StringBuffer();
//
//        return  result.doOnNext(chunk->{
//            codeBuilder.append(chunk);
//
//        }).doOnComplete(()->{
//            String completeMultiFileCode = codeBuilder.toString();
//            MultiFileResult multiFileResult = CodeParser.parseMultiFileCode(completeMultiFileCode);
//            CodeFileSaver.saveMultiFileResult(multiFileResult);
//        });
//
//    }
}
